#pragma  once
#include "Configuration.h"

// implementation of smart ptrs can be changed
#ifdef LE_BOOST_SHARED_PTR
#include "Weak_ptr_Impl_boost.h"
#else
#include "Weak_ptr_Impl_own.h"
#endif

namespace PimplImplementation
{
	template<typename T>
	class Shared_ptr_Impl;
}

namespace Boon
{
	template<class T>
	class Shared_ptr;

	template<class T>
	class Weak_ptr
	{
		template<typename T>
		friend class Boon::Shared_ptr;
		template<typename Y>
		friend class Boon::Weak_ptr;

	public:
		Weak_ptr();
		Weak_ptr( const Weak_ptr<T>& o );
		template<typename Y> Weak_ptr( const Weak_ptr<Y>& o );
		Weak_ptr( const Boon::Shared_ptr<T>& o );
		template<typename Y> Weak_ptr( const Boon::Shared_ptr<Y>& o );

		Boon::Shared_ptr<T> Lock() const;

		long UseCount() const;

		bool Expired() const;

		bool Empty() const;

		void Reset();

		const Weak_ptr<T>&			operator=( const Weak_ptr<T>& rhs );

		const Weak_ptr<T>&			operator=( const Boon::Shared_ptr<T>& rhs );

		operator bool() const;

	private:

		PimplImplementation::Weak_ptr_Impl<T>		m_Implementation; /*!< Implementation of this class hidden in namespace PimplImplementation */

	};

#pragma region Implementation Forwarding to Weak_ptr_Impl-Class

	template<class T>
	Boon::Weak_ptr<T>::Weak_ptr()
		: m_Implementation()
	{

	}

	template<class T>
	Boon::Weak_ptr<T>::Weak_ptr( const Weak_ptr<T>& o )
		: m_Implementation( o.m_Implementation )
	{

	}
	
	template<typename T>
	template<typename Y>
	Boon::Weak_ptr<T>::Weak_ptr( const Weak_ptr<Y>& o )
		: m_Implementation( o.m_Implementation )
	{

	}

	template<class T>
	Boon::Weak_ptr<T>::Weak_ptr( const Boon::Shared_ptr<T>& o )
		: m_Implementation( o.m_Implementation )
	{

	}

	template<typename T>
	template<typename Y>
	Boon::Weak_ptr<T>::Weak_ptr( const Boon::Shared_ptr<Y>& o )
		: m_Implementation( o.m_Implementation )
	{

	}

	template<class T>
	Boon::Shared_ptr<T> Boon::Weak_ptr<T>::Lock() const
	{
		return Shared_ptr<T>( *this );
	}

	template<class T>
	long Boon::Weak_ptr<T>::UseCount() const
	{
		return m_Implementation.UseCount();
	}

	template<class T>
	bool Boon::Weak_ptr<T>::Expired() const
	{
		return m_Implementation.Expired();
	}

	template<class T>
	bool Boon::Weak_ptr<T>::Empty() const
	{
		return m_Implementation.Empty();
	}

	template<class T>
	void Boon::Weak_ptr<T>::Reset()
	{
		return m_Implementation.Reset();
	}

	template<class T>
	const Boon::Weak_ptr<T>& Boon::Weak_ptr<T>::operator=( const Boon::Weak_ptr<T>& rhs )
	{
		m_Implementation = rhs.m_Implementation;
		return *this;
	}

	template<class T>
	const Weak_ptr<T>& Boon::Weak_ptr<T>::operator=( const Boon::Shared_ptr<T>& rhs )
	{
		m_Implementation = rhs.m_Implementation;
		return *this;
	}

	template<class T>
	Boon::Weak_ptr<T>::operator bool() const
	{
		return m_Implementation.Empty() == false;
	}
	
#pragma endregion

}
